home *** CD-ROM | disk | FTP | other *** search
/ HyperLib 1997 Winter - Disc 1 / HYPERLIB-1997-Winter-CD1.ISO.7z / HYPERLIB-1997-Winter-CD1.ISO / オンラインウェア / PRG / Z80ppc 160.sit / Z80ppc 160 / Z80_ppc.doc < prev    next >
Text File  |  1995-11-19  |  15KB  |  270 lines

  1.  
  2.         Z80_ppc.doc                                                 19.Nov.95 KIO !
  3.     
  4.         Documentation for the C coded Z80 emulator
  5.  
  6.  
  7. Legal note
  8.  
  9. Z80 engine C coded (intended for PowerPCs)
  10. Copyright (C) 1994-1995
  11. G殤ter Woigk
  12. N殲nberger Str. 79
  13. 91052 Erlangen
  14. Germany
  15. email: kio@vanilla.nbg.sub.org
  16.     
  17. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of  the License, or (at your option) any later version.
  18.  
  19. This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.
  20.  
  21. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  22.  
  23.  
  24. General
  25.  
  26. The Z80_PowerPC package is a C coded emulator of the Zilog Z80 CPU. It is designed for high speed and easy to use. Though if you include all options, it becomes slower and harder to understand...
  27.  
  28. Actually it was written to drive Mac Spectacle, the Sinclair ZX Spectrum emulator from the same author. (oh yes, that's me!)
  29.  
  30.     Features:
  31.     ・    all legal instructions
  32.     ・    all known illegal instructions (nearly no opcode gaps)
  33.     ・    all flags (8 bit)
  34.     ・    exact T cycle counting
  35.         -> exact speed
  36.         -> timing loop depending sound
  37.         -> timing loop depending tape i/o
  38.         -> highres screen update
  39.     ・    ROM write protection (except stack operations)
  40.     ・    exact R register emulation
  41.     ・    1 instruction latency after EI
  42.     ・    Info calls for all illegal and some interesting instructions
  43.     ・    instruction and address profiling
  44.     ・    Single stepping
  45.  
  46.     global struct zreg keeps z80 registers on entry/return of Z80_PPC()
  47.     some registers are copied to local variables while Z80_PPC() is running
  48.     global pointer CORE points to 0x10000 bytes of memory to use as z80 memory
  49.     macro rompoke(A,N) and rompoke2(A,nn) provide means for ROM write protection
  50.     
  51.     Z80_PPC() does this:
  52.     1.    process NMI, if NMI is pending
  53.     2.    process interrupt, if IRPT is pending and not disabled
  54.     3.    execute z80 instructions, until T cycle counter expires
  55.         IRPTs are only tested again after an EI instruction
  56.     4.    if T cycle counter reaches 0, Do_Cycles() is called and may
  57.         ・    reload the T cycle counter
  58.         ・    trigger NMI or IRPT
  59.         ・    require Z80_PPC() to exit
  60.  
  61.     If Z80() returns, it's result value indicates one of the following conditions:
  62.     ・  EXIT was set by Do_Cycles()
  63.     ・  not supported instruction at zreg.IP
  64.     ・  halt instruction executed at zreg.IP-1
  65.     ・  rst0 instruction executed at zreg.IP-1
  66.     ・  illegal interrupt mode / not supported instruction in interrupt mode 0
  67.  
  68.     Single instructions may be executed by calling Z80_PPC() with CYCLES=4
  69.     Then one of the following is processed: (in priority order)
  70.     ・  handle nmi request
  71.     ・  handle irpt request (if interrupts are enabled)
  72.     ・  execute one instruction, except:
  73.     ・  if instruction is EI, handle EI and next instruction in one go
  74.  
  75. The emulator is fast enough to run the Z80 at approx. 16 MHz on a 66 MHz PowerPC, though this varies depending on the opcode mix; and regular refresh of the a virtual screen and event polling from the Mac OS will slow it down - potentially to a crawl.
  76.  
  77.  
  78. The emulator is "nearly bug-free". If you really locate any error in it please inform me at once. My e-mail address is given above!
  79.  
  80.  
  81. Files
  82.  
  83. codes.c
  84. the normal z80 instructions; included in z80.ppc.c
  85.  
  86. codesCB.c
  87. extended z80 instructions prefixed by CBh, included in codes.c
  88.  
  89. codesED.c
  90. extended z80 instructions prefixed by EDh, included in codes.c
  91.  
  92. codesXX.c
  93. index register instructions prefixed by DDh or FDh, included in codes.c
  94.  
  95. init_z80.c
  96. initialization of the z80 engine and some utilities
  97.  
  98. kio.h
  99. my standard header definitions.
  100. most important to know:  Char  = unsigned char;  Short  = unsigned short
  101.  
  102. z80.h
  103. definition of constants, data and functions
  104.  
  105. z80.options
  106. switches for compiler options (profiling, info calls, etc.)
  107.  
  108. z80.ppc.c
  109. the main source file, includes codesCB.c, codesED.c  and codesXX.c
  110.  
  111. z80.ppc.macros
  112. definitions of macros used in z80.ppc.c, partly depending on switches in z80.options
  113.  
  114.  
  115. Procedures
  116.  
  117. All procedures except Z80_PPC()  are defined in Init_z80.c
  118.  
  119. In preparation for paged memory cores the following functions are provided and intended to be by from the application which incorporates the z80 emulator. They are not used by the emulator itself.
  120.  
  121. Char*    RdPtr    ( Short addr );
  122. get a pointer to a byte in the z80 core which you want to read.
  123. note: if you want to read multiple bytes (even only a word) do not simply increment the pointer but use RdPtr()  repeatedly unless you check for page boundaries yourself.
  124.  
  125. Char*    WrPtr    ( Short addr );
  126. get a pointer to a byte in the z80 core which you want to write.
  127. note: RdPtr()  and WrPtr()  may give different pointers for the same address if that address is not RAM. Thereby ROM write protection is achieved.
  128.  
  129. Char    Peek    ( Short addr );
  130. read a byte from the z80 core. Normally more useful than using RdPtr()
  131.  
  132. Poke    ( Short addr, Char byte );
  133. write a byte to the z80 core. Normally more useful than using WrPtr()
  134.  
  135.  
  136. To ease block access to the z80 core, the following functions are provided:
  137.  
  138. OSErr    Buffer2File    ( void* bu,    short fileID,    long len );
  139. store arbitrary memory in a file. the file must be open and positioned as desired.
  140.  
  141. OSErr    File2Buffer    ( short fileID,    void* bu,        long len );
  142. load arbitrary memory from file.
  143.  
  144. OSErr    Core2File        ( Short addr,    short fileID,    long len );
  145. store z80 core in a file.
  146.  
  147. OSErr    File2Core        ( short fileID,    Short addr,    long len );
  148. load z80 core from file
  149.  
  150. Core2Buffer    ( Short addr,    void* bu,        long len );
  151. copy z80 core to arbitrary memory
  152.  
  153. Buffer2Core    ( void* bu,    Short addr,    long len );
  154. copy arbitrary memory to z80 core
  155.  
  156. Core2Core    ( Short src,    Short dest,    long len );
  157. copy z80 core to z80 core
  158.  
  159. Buffer2Buffer    ( void* src,    void* dest,    long len );
  160. for completeness
  161.  
  162. long        tfu;
  163. if a file operation returns with an error, examine tfu  to see how many bytes were read or written.
  164.  
  165.  
  166. The main functions:
  167.  
  168. InitZ80 ( int hardware );
  169. allocate memory for the z80 core, set up registers for the z80 engine and calculate some tables. actually there are two constants defined in z80.h:  zx48k  and zx128  for the ZX Spectrum and the ZX Spectrum 128. The code for InitZ80()  may look a little bit weird for it contains some code only required for the 68k assembler coded z80 engine.
  170.  
  171. short    Z80_PPC ( );
  172. this is the c coded z80 engine. To use it, follow these steps:
  173. 0) provide at least Do_Input(),  Do_Output()  and Do_Cycles()  as described below
  174. 1) call InitZ80()  to set up the z80 core and reset the z80 cpu
  175. 2) set variable CYCLES  to the amount of T cycles you whish the z80 cpu to run uninterrupted.
  176. 3) call Z80_PPC().  it's return value idicates the reason why it terminated.
  177. 4) perform propper actions to handle this reason
  178. 5) resume at step 2
  179.  
  180.  
  181. The following functions must be supplied in your application:
  182.  
  183. Do_Output ( Short addr, Char n );
  184. everytime an out statement is executed, the z80 engine calls this funtion. It is your responsibility to handle it in that way the emulated hardware would do. If you need information about the exact time examine variable CYCLES  which has been counted down by the z80 engine (see below).
  185.  
  186. Char Do_Input ( Short addr );
  187. called to handle input statements.
  188.  
  189. Do_Cycles ( void );
  190. is called when the z80 cycle counter CYCLES  reaches zero. If you don't want that Z80_PPC()  terminates you must reload it and you may set WUFF  to indicate an interrupt or NMI. Otherwise you must set EXIT.  Personally i use Do_Cycles()  only to refresh screen memory in high resolution mode and normally Do_Cycles()  just sets EXIT  to force Z80_PPC()  to terminate. Then i do event polling and screen refresh, wait some time if the z80 engine is too fast, flag an interrupt and restart Z80_PPC().
  191.  
  192. write_to_rom    ( Short A, Char N);
  193. Actually the z80 engine not yet supports the paged memory model which would give it automatic ROM protection. So everytime the Z80 cpu writes to adresses 0000h - 3FFFh this function is called and the byte is not written. The macro for writing to the core, which includes this ROM check, is defined in z80.ppc.macros.  This function will no longer be called when the paged memory model is implemented.
  194.  
  195. Z80_Info ( long cc, Short ip );
  196. Optional: define INFO_MISC  in z80.options  as true, to include calls to Z80_Info()  in certain 'interesting' instructions. If you do not define INFO_MISC,  you need not to define Z80_Info(). 
  197.  
  198. Z80_Info_Irpt ( long cc );
  199. Optional: define INFO_IRPT  in z80.options  as true, to include calls to Z80_Info_Irpt()  in normal interrupt processing.
  200.  
  201. Z80_Info_NMI ( long cc );
  202. Optional: define INFO_NMI  in z80.options  as true, to include calls to Z80_Info_NMI()  in normal interrupt processing.
  203.  
  204. Z80_1st_Loc ( long cc, Short ip );
  205. Optional: define PC_PROFILE  in z80.options  as true, to include PC profiling for the Z80 cpu in Z80_PPC().  This includes the following code in the z80 instruction dispatcher:
  206. 1) test count_pc  to see, whether pc profiling is actually enabled
  207. 2) if so, increment cnt_pc[opcode]
  208. 3) if cnt_pc[opcode]  becomes 0, call Z80_1st_Loc()
  209. Note, that you have to supply not only this function, but also allocate the array cnt_pc[]  in your application. cnt_pc  is only defined as a pointer in init_z80.c;  enabling count_pc  before allocating an array for cnt_pc  will crash the system.
  210. Note too, that for the convenience of the 68k assembler coded z80 engine cnt_pc[]  should be initialized with -1 to indicate 'not yet executed', so incrementing a cell for the first time makes it zero and Z80_first_Loc()  is called.
  211.  
  212. Z80_1st_Instr ( long cc, Short ip );
  213. Optional: define INSTR_PROFILE  in z80.options  as true, to include instruction profiling for the Z80 cpu. This is handled similar to PC profiling, except that Z80_1st_Instr()  is called and variable count_instr  is used as enable-flag and the instructions are counted in cnt_xx[]  (normal instructions), cnt_CB[],  cnt_ed[],  cnt_xy[]  (for both, IX and IY instructions) and cnt_xycb[]  (for CBh prefixed index register instructions).
  214.  
  215.  
  216. The z80 registers and associated data structure
  217.  
  218. All registers of the z80 cpu are kept in a struct which is defined in z80.h.  This struct is set up to accomodate the 68k assembler coded z80 engine and you may simply ignore it's layout for the C coded engine because i have added a lot of defines to map all z80 registers to easy names. e.g. DE  is the de double register (not in z80 byte order!) and RD  (read: Register D) and RE  are the d and e byte registers. 
  219.  
  220. CYCLES is the z80 processor T cycle counter and it is decremented each instruction according to the number of T cycles this instruction takes. Shortest instructions take a minimum of 4 T cycles at least, the longest instructions take 23 T cycles. On the ZX Spectrum, running at 3.5 MHz, every second has 3,500,000 T cycles. An interrupt is generated ever 1/50 sec, therefore i set CYCLES  to 70,000, that is 3,500,000/50 every time I call Z80_PPC().  Note, that wait cycles are not implemented. So the emulator runs at the same speed in the video bank as in other RAM or ROM, for example. Computers which syncronize cpu memory access and DMA or video memory access in a fixed manner like the Amstrad CPC computers, may be emulated correctly if you rework the timing instructions in the source of Z80_PPC().  (have a nive time!)
  221. If you do this, do it be rewriting some macros, so that the normal timing is not completely discarded from the source and give me a copy!
  222.  
  223. TOTAL is not used by the z80 engine itself. But every time I increment CYCLES  by 70,000 I increment TOTAL  by the same value. CYCLES  is decremented by the z80 cpu, TOTAL  not. So the total amount of T cycles executed so far can be calculated by TOTAL-CYCLES.  Cave at: TOTAL  overflows approx. every 20 minutes.
  224.  
  225. EXIT is a flag that, if set, forces Z80_PPC()  to abort. It is only testesd after CYCLES  reaches 0, You should set EXIT  in Do_Cycles()  if you don't reload CYCLES  as stated above.
  226.  
  227. WUFF contains the NMI and normal interrupt flags. NMI flag is bit 7, the remaining bits are a counter for pending interrupts and should normally only be set to 0 or 1 too.
  228.  
  229. RI is the i register of the z80 cpu; IRPTCMD is the byte the z80 cpu reads in it's interrupt acknowledge cycle and it is preset by InitZ80()  to FFh. In interrupt mode 1 both are ignored. In mode 2 they are combined to address the interrupt table. If you emulate hardware which generates an interrupt vector, you must put it in IRPTVEK  when you set WUFF  and call Z80_PPC()  or return from Do_Cycles().   Most popular z80 computers didn't incorporate such hardware. In interrupt mode 0 the byte from IRPTVEK  is treated as z80 instruction and executed. Normally this is FFh - the RST 38h opcode; and this is actually the only supported opcode in irpt mode 0.
  230.  
  231. RR is the r register. Depending on the setting of EXACT_R  in z80.options,  all 8 bits or only the high bit is significant.
  232.  
  233.  
  234. Return values of Z80_PPC()
  235.  
  236. (check z80.h  for defines and whether i have renumbered them again...)
  237.  
  238. 0    Watchdog exception. WUFF  was set after calling Do-Cycles()  after CYCLES  reached zero. The watchdog flag in WUFF  should be cleared befor Z80_PPC()  is called again. Mac Spectacle uses watchdog interrupts to poll Mac OS events and update the ZX Spectrum screen.
  239.  
  240. 1    A not implemented instruction was executed. PC  points to the first byte of the incriminated opcode. This can no longer happen, for all opcodes are decoded.
  241.  
  242. 2    The Z80 instruction HALT was executed. The application should poll Mac OS events until an NMI or normal interrupt occurs. If interrupts are disabled, you must only wait for NMI's. 
  243.  
  244. 3    The Z80 instruction RST 0 was executed. This opcode is trapped as a possibility to call C coded functions to perform some system routines quicker than they were performed emulating the Z80 code. To decide which system function must be emulated, check the current PC , which points to the next instruction. Z80_PPC()  does nothing except returning with this code, when a RST 0 is executed. If you want to make the RST 0 opcode just do what it does on a real Z80, push the PC on the stack and set the PC to 0x0000.
  245.  
  246. 4   Interrupt error. An interrupt in mode 0 with IRPTVEK != FFh occured.
  247.  
  248. 5-7   An illegal instruction was executed at PC -2/-3/-4. INFO_ILLEGALS  must be set to true in z80.options  or those calls won't be included in the engine.
  249.  
  250. 8-11   A weird illegal instruction was executed at PC -1/-2/-3/-4. INFO_WEIRD  must be set to true in z80.options  or those calls won't be included in the engine.
  251.  
  252.  
  253. Trace Mode
  254.  
  255. To trace the z80, simply set CYCLES  to 4 before calling Z80_PPC().  This allows one instruction to be executed before the counter overflows. Then Do_Cycles()  will be called and you have the chance to set WUFF  thus forcing Z80_PPC()  to terminate.
  256.  
  257. Note, that you have to take special care to detect interrupt processing, which consumes time and will take place instead of executing an instruction if you do not inhibit interrupt generation. Note too, that EI and the next instruction are performed in one go.
  258.  
  259.  
  260.            ... KIO !
  261.  
  262.  
  263.  
  264.  
  265.  
  266.  
  267.  
  268.  
  269.  
  270.